package com.zking.utils;

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;

/**
 * 	文件在线存储和下载
 * @author 我爱陈果果
 */
public class FileOSSUtils {
	
	private Properties p = null;
	// Endpoint以杭州为例，其它Region请按实际情况填写。
	private String endpoint;
	// 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
	private String accessKeyId;
	//密钥
	private String accessKeySecret;
	//根目录
	private String bucketName;
	
	public FileOSSUtils() throws Exception {
		p = getProperties("files.properties");
		endpoint = p.getProperty("endpoint");
		accessKeyId = p.getProperty("accessKeyId");
		accessKeySecret = p.getProperty("accessKeySecret");
		bucketName = p.getProperty("bucketName");
	}
	
	/**
	 * 	文件上传
	 * @param in 需要上传文件的流
	 * @param savePath 存储的路径，包括文件名
	 */
	public void uploadFile(InputStream in, String savePath) {
		// 创建OSSClient实例。操作云端数据的客户端
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
		//调用putObject上传文件
		ossClient.putObject(bucketName, savePath, in);
		// 关闭OSSClient。
		ossClient.shutdown();
		
		
	}
	
	/**
	 * 	下载云端文件
	 * @param out 将文件写入本地的一个输出流（也可以是response的输出流）
	 * @param dowloadPath
	 * @param savePath
	 * @throws IOException
	 */
	public void downloadFile(OutputStream out, String dowloadPath) throws IOException {
		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

		// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
		OSSObject ossObject = ossClient.getObject(bucketName, dowloadPath);
		//获取云端文件的输入流
		InputStream in = ossObject.getObjectContent();

		
		//将文件写入输出流
		int len = 0;
		byte[] b = new byte[1024];
		BufferedOutputStream bos = new BufferedOutputStream(out);
		while ((len = in.read(b)) != -1) {
			bos.write(b, 0, len);
		}
		bos.close();
		in.close();
		// 关闭OSSClient。
		ossClient.shutdown();
	}
	/**
	 * 获取文件的输入流
	 * @param path
	 * @return
	 */
	public InputStream getInStream(String path) {
		
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

		// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
		OSSObject ossObject = ossClient.getObject(bucketName, path);
		//获取云端文件的输入流
		InputStream in = ossObject.getObjectContent();
		
		return in;
	}
	/**
	 * 	传入文件夹路径，删除文件或者文件夹
	 * @param objectName 删除文件的路径。如需删除文件夹，<br>
	 * 请将ObjectName设置为对应的文件夹名称。如果文件夹非空，<br>
	 * 则需要将文件夹下的所有object删除后才能删除该文件夹。<br>
	 */
	public void deleteFile(String objectName) {
		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

		// 删除文件。如需删除文件夹，请将ObjectName设置为对应的文件夹名称。如果文件夹非空，
		//则需要将文件夹下的所有object删除后才能删除该文件夹。
		ossClient.deleteObject(bucketName, objectName);

		// 关闭OSSClient。
		ossClient.shutdown();
	}
	
	
	/**
	 * 	判断文件是否存在
	 * @param 查询文件的路径
	 */
	public boolean isexist(String filePath) {

		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

		// 判断文件是否存在。doesObjectExist还有一个参数isOnlyInOSS，如果为true则忽略302重定向或镜像；如果
		//为false，则考虑302重定向或镜像。
		boolean found = ossClient.doesObjectExist(bucketName, filePath);
		// 关闭OSSClient。
		ossClient.shutdown();
				
		return found;
	}
	
	/**
	 * 	列举指定根目录下所有的文件，默

	 * @param KeyPrefix 指定查询的文件前缀，也就是指定的文件夹路径
	 * @return 所有文件路径的目录，包括文件夹
	 */
	public List<String> listOSSFiles(String KeyPrefix){
		//存储文件路径的集合
		List<String> listFiles = new ArrayList<String>();
			
		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

		// 列举文件。 如果不设置KeyPrefix，则列举存储空间下所有的文件。KeyPrefix，则列举包含指定前缀的文件。
		ObjectListing objectListing = ossClient.listObjects(bucketName, KeyPrefix);
		List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
		for (OSSObjectSummary s : sums) {
			listFiles.add(s.getKey());
		}

		// 关闭OSSClient。
		ossClient.shutdown();
		return listFiles;
	}
	
	/**
	 * 	查询指定数量的文件个数，最大1000
	 * @param maxKeys 指定的最大条数，默认100，最大1000
	 * @param KeyPrefix 指定查询前缀，默认为查询所有
	 * @return
	 */
	public List<String> listOSSFilesRequest(int maxKeys, String KeyPrefix) {
		//存储文件路径的集合
		List<String> listFiles = new ArrayList<String>();
		// 创建OSSClient实例
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
		
		// 列举文件。
		ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName)
				.withMaxKeys(maxKeys).withPrefix(KeyPrefix));
		List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
		for (OSSObjectSummary s : sums) {
			listFiles.add(s.getKey());
		}

		// 关闭OSSClient。
		ossClient.shutdown();
		return listFiles;					
	}
	
	
	
	/**
	 * 	通过这个类的反射获取项目的根目录，最终得到一个Properties对象
	 * @param prosPath Properties文件的路径
	 * @return 加载了Properties文件的对象
	 * @throws Exception 
	 */
	public Properties getProperties(String prosPath) throws Exception {
		//1.创建一个properties对象
		//这个对象里面就有操作这个properties文件所有方法
		Properties pros = new Properties();
		//2.获取源文件的字节输入流
		InputStream inStream = null;
		try {
			//class文件所在的位置的根目录。
			String path = FileOSSUtils.class.getResource("/").getPath();
			//将中文的url编码解析%ert%weq
			path = URLDecoder.decode(path, "utf-8");
			inStream = new FileInputStream(path + "\\" + prosPath);
			//3.properties对象加载源文件
			pros.load(inStream);
		} catch (FileNotFoundException e) {
			throw new FileNotFoundException("Properties文件路径未找到!");
		} catch (IOException e) {
			throw new IOException("Properties文件流加载失败!");
		}
		return pros;
	}
	
	
	
	public static void main(String[] args) {
		try {
			FileOSSUtils fileOSSUtils = new FileOSSUtils();
			
			//文件上传
//			InputStream in = new FileInputStream("E:\\工作\\破解教程.docx");
//			String savePath = "gc0910/middleProject/group1/product/"+UUID.randomUUID()+".docx";
//			fileOSSUtils.uploadFile(in, savePath);
//			System.out.println("文件上传成功！");
			
			//云端的文件夹不可能让你去遍历的
			//1.从数据库把所有要下载的地址用集合或者数组存起来
			//2.循环调用downloadFile()方法就是批量下载了
			//文件下载
			String savePath = "D:\\e9a9048b40b2.jpg";
			OutputStream out = new FileOutputStream(savePath);
			String dowloadPath = "gc0910/middleProject/group1/food4c8c4f25-75bd-4cd1-9698-e9a9048b40b2.jpg";
			fileOSSUtils.downloadFile(out, dowloadPath);
			System.out.println("下载成功！");
			
//			List<String> listFiles = fileOSSUtils.listOSSFiles("gc0910/middleProject/group4/res/static");
//			for (String key : listFiles) {
//				System.out.println(key);
//				//删除
////				fileOSSUtils.deleteFile(key);
//			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
